﻿// Copyright (c) Inossem. All rights reserved.
// Licensed under the LGPL-3.0 license. See LICENSE file in the project root for full license information.
using DWF.Studio.Custom;
using DWF.Studio.Host.RemoteHandler;
using DWF.Studio.Project;
using DWF.Studio.RemoteCtrls;
using DWF.Studio.RemoteCtrls.Proxy;
using DWF.Studio.Script;
using DWF.Studio.Script.Excutor;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DWF.Studio.Host
{
    /// <summary>
    /// 远程加载器本地宿主
    /// </summary>
    internal class RemoteLoaderHost
    {
        private static RemoteLoaderHost _instance = null;
        private static object _locker = new object();


        /// <summary>
        /// 创建加载器宿主实例
        /// </summary>
        /// <param name="projectPath">工程路径</param>
        /// <param name="packageInfos">依赖包信息</param>
        /// <returns></returns>
        public static RemoteLoaderHost CreateInstance(Func<Dictionary<string, string>> projectPropertiesFunc, List<PackageInfo> packageInfos)
        {
            lock (_locker)
            {
                if (_instance != null)
                {
                    _instance.Unload();
                }

                var paths = new List<string>();

                var projectProperties = projectPropertiesFunc();
                var projectPath = projectProperties["projectDirectory"];
                var libs = System.IO.Path.Combine(projectPath, StaticResource.ProjectSelfLibs);//工程文件夹libs的绝对路径
                paths.Add(libs);
                var baseDirectory = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory).Parent.FullName;//用项目文件双击启动路径会有问题
                foreach (var package in packageInfos)//每个依赖包的绝对路径
                {
                    var activityPath = System.IO.Path.Combine(baseDirectory, StaticResource.Activities, String.Format(@"{0}.{1}", package.Id, package.Version), StaticResource.ActivitiesLib, package.TargetFramework);//System.IO.Path.GetFullPath("..")
                    paths.Add(activityPath);
                }

                var pathsArray = paths.ToArray();

                ScriptExecutorSet.WorkflowExcutor.SetSearchPaths(pathsArray);

                var prober = new TypeProber(new string[] { libs });
                var assemblies = prober.ProbeAssemblies();

                ScriptExecutorSet.WorkflowExcutor.SetLoadAssemblyNames(assemblies);

                ScriptExecutorSet.WorkflowExcutor.SetProjectProperties(projectPropertiesFunc);

                return _instance = new RemoteLoaderHost(projectPropertiesFunc, pathsArray, new string[] { libs });
            }
        }
        /// <summary>
        /// 获取当前实例
        /// </summary>
        /// <returns></returns>
        public static RemoteLoaderHost GetCurrentInstance()
        {
            return _instance;
        }

        /// <summary>
        /// 在目标路径下，探测活动库。
        /// </summary>
        /// <param name="searchPaths"></param>
        /// <returns></returns>
        public static string[] ProbeActivity(string[] searchPaths)
        {
            string[] activityNames = null;
            var prober = new TypeProber(searchPaths);
            activityNames = prober.ProbeActivities();

            return activityNames;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="resolutionPaths">AppDomain解析路径</param>
        private RemoteLoaderHost(Func<Dictionary<string, string>> projectPropertiesFunc, string[] resolutionPaths, string[] shadowPaths)
        {
            _projectPropertiesFunc = projectPropertiesFunc;
            _resolutionPaths = resolutionPaths;
            _shadowPaths = shadowPaths;
        }

        /// <summary>
        /// AppDomain解析路径
        /// </summary>
        private string[] _resolutionPaths = null;

        /// <summary>
        /// AppDomain解析路径
        /// </summary>
        private string[] _shadowPaths = null;

        private Func<Dictionary<string, string>> _projectPropertiesFunc = null;

        /// <summary>
        /// 远程加载器
        /// </summary>
        private CtrlRemoteLoader _loader = null;

        private XamlAnalyzerProxy _xamlAnalyzer = null;

        private DragDropProxy _dragDropProxy = null;

        /// <summary>
        /// 锁同步对象
        /// </summary>
        private object _obj = new object();

        /// <summary>
        /// 获取远程加载器
        /// </summary>
        /// <returns></returns>
        private CtrlRemoteLoader getLoader()
        {
            if (_loader == null)
            {
                lock (_obj)
                {
                    if (_loader == null)
                    {
                        var func = new GenericFuncHandlerHandler<Dictionary<string, string>>();
                        func.SetFunc(this._projectPropertiesFunc);
                        _loader = new CtrlRemoteLoader(func.Invoke, _resolutionPaths, _shadowPaths);
                        _xamlAnalyzer = _loader.LoadXamlAnalyzerProxy();
                        _dragDropProxy = _loader.LoadDragDropProxy();
                    }
                }
            }
            return _loader;
        }

        /// <summary>
        /// 加载设计器代理
        /// </summary>
        /// <param name="projectDirectory"></param>
        /// <returns></returns>
        public ActivityDesignerProxy LoadDesignerProxy()
        {
            var loader = getLoader();

            return loader.LoadDesignerProxy();
        }

        /// <summary>
        /// 加载工具箱代理
        /// </summary>
        /// <returns></returns>
        public ActivityToolBoxProxy LoadToolBoxProxy()
        {
            var loader = getLoader();

            return loader.LoadToolBoxProxy();
        }

        ///// <summary>
        ///// 加载片段管理器代理
        ///// </summary>
        ///// <returns></returns>
        public SnippetExplorerProxy LoadSnippetProxy()
        {
            var loader = getLoader();

            return loader.LoadSnippetExplorerProxy();
        }

        ///// <summary>
        ///// 加载查询代理
        ///// </summary>
        ///// <returns></returns>
        public SearchExplorerProxy LoadSearchProxy()
        {
            var loader = getLoader();

            return loader.LoadSearchProxy();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public XamlAnalyzerProxy LoadXamlAnalyzerProxy()
        {
            return _xamlAnalyzer;
        }

        public DragDropProxy LoadDragDropProxy()
        {
            return _dragDropProxy;
        }

        /// <summary>
        /// 卸载远程appdomain。
        /// </summary>
        public void Unload()
        {
            if (_loader != null)
            {
                lock (_obj)
                {
                    if (_loader != null)
                    {
                        _xamlAnalyzer?.Dispose();
                        _xamlAnalyzer = null;

                        _dragDropProxy?.Dispose();
                        _dragDropProxy = null;

                        _loader.Unload();
                        _loader = null;
                    }
                }
            }
        }
    }
}
